#ifndef __BASIC_UTILS_H__
#define __BASIC_UTILS_H__

#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include "basic/types.h"
#include "basic/platform.h"

namespace basic
{
/*
struct SLibraryLoadResult
{
    bool success;
    HMODULE handle;
    std::string msg;
};

DLL_API SLibraryLoadResult LoadWindowsDLL(const char *URL, const char *funcName,
void **func); DLL_API bool UnloadWindowsDLL(HMODULE handle); #ifdef M_DEBUG
DLL_API extern void LogInfo(const char *msg);
DLL_API extern void LogFatal(const char *msg);
#else
DLL_API extern void LogInfo(const char *msg){};
DLL_API extern void LogFatal(const char *msg){};
#endif
DLL_API bool CalculateFPS(float &fps);
DLL_API const char *GetVersion();
DLL_API int CreateUUID();

DLL_API void StringSplit(std::string s, std::vector<std::string> *out, char
delimiter);
*/

uint32_t gGetNextUniqueNumberID();

template <typename T>
bool gIsExistInVector(const std::vector<T>& vec, T value)
{
    return std::find(vec.cbegin(), vec.cend(), value) != vec.cend();
}

template <typename T>
bool gRemoveFromVector(std::vector<T>& vec, const T& value)
{
    auto it = std::find(vec.begin(), vec.end(), value);
    if (it != vec.end())
    {
        vec.erase(it);
        return true;
    }
    return false;
}

template <typename T>
bool gAddToVector(std::vector<T>& vec, T value, bool force)
{
    auto it = std::find(vec.begin(), vec.end(), value);
    if (it == vec.end() || force)
    {
        vec.push_back(value);
        return true;
    }
    return false;
}

namespace utils
{

    template <typename T>
    bool ClearQueue(std::queue<T>& que)
    {
        while (!que.empty())
        {
            que.pop();
        }
        return true;
    }

    template <typename T>
    bool RemoveFromQueue(std::queue<T>& que, const T& value)
    {
        if (que.empty())
        {
            return false;
        }

        const auto& _backElement = que.back();
        auto& _tmp = que.front();
        while (true)
        {
            if (_tmp == value)
            {
                que.pop();
                return true;
            }
            if (_backElement == _tmp)
            {
                return false;
            }
            que.pop();
            que.push(_tmp);
            _tmp = que.front();
        }
        return false;
    }

} // namespace utils

} // namespace basic

#endif
